(function(win){
	var scriptID = 0;
	var ready=function*(){
		var scripts = win.Array.from(win.document.getElementsByTagName("script"));
		for(var script of scripts){
			var engine = win.coro.engines[script.type];
			if(!engine) continue;

			if(!script.hasAttribute("id")) script.setAttribute("id", "__coro" + (scriptID++));
			
			yield* engine(script, script.innerText);
		}
	}

	// The ready event handler and self cleanup method
	var completed=()=>{
		win.document.removeEventListener( "DOMContentLoaded", completed );
		win.removeEventListener( "load", completed );
		win.coro.run(ready);
	}

	// Catch cases where $(document).ready() is called
	// after the browser event has already occurred.
	// Support: IE <=9 - 10 only
	// Older IE sometimes signals "interactive" too soon
	if ( win.document.readyState === "complete" ||
		( win.document.readyState !== "loading" && !win.document.documentElement.doScroll ) ) {

		win.coro.run(ready);

	} else {

		// Use the handy event callback
		win.document.addEventListener( "DOMContentLoaded", completed );

		// A fallback to win.onload, that will always work
		win.addEventListener( "load", completed );
	}





	win.Promise = Promise;

	var coro = win.coro = function(gen, thread){
		switch((typeof gen)[0]){
			case "f": //function
				return coro.run(function*(){ yield* coro.eval("(" + gen.toString() + ")()"); });
			case "s": //string
				return coro.run(function*(){ return yield* coro.eval(gen) });
			case "o": //object
				throw "Not support";
			case "u": //undefined
			case "1": //number
				thread = gen;
				var script = win.document.currentScript.previousElementSibling;
				return coro.run(
					function*(){ return yield* coro.eval(script.innerText) }, this, thread
				);
		}
	};

	coro.engines = {
		"text/coro":function*(script, source){
			yield* coro.eval(source);
		}
	};

	coro.promise = function(fn){
		this._pormise = new Promise(fn);
	}

	coro.promise.prototype = {
		then(result){
			return this._pormise.then(result);
		}
	};

	coro.threads = window.coro.threads || [];
	coro.run = function(fn, thisCtx, threadIndex=0){
//console.log(coro.threads[threadIndex] && coro.threads[threadIndex].running, fn.toString());
		var thread = coro.threads[threadIndex] || (coro.threads[threadIndex] = {});
		var start, promise = new coro.promise(function(resolve, reject){
			start = function(){
				if(promise.started) throw new Error("recall start"); else promise.started = true;
				if(promise.prev){
					promise.prev.next = promise.next;
					if(promise.next){
						promise.next.prev = promise.prev;
						promise.next = null;
					}
					promise.prev = null;
				};

				var fun = fn.call(thisCtx), callee, reject2 = function(error){
					//if(!root) thread.running = false;
					reject(error);
				}, resolve2 = function(result){
					if(result instanceof Promise || result instanceof coro.promise){
						if(result.start) result.start();
						result.then(resolve2, reject2);
					} else {
						callee(result);
					}
				}, resolve3 = function(result){
					if(result instanceof Promise || result instanceof coro.promise){
						if(result.start) result.start();
						result.then(resolve3, reject2);
					} else {
						resolve(result);
					}
				};
				(callee = function(result){
					var time = new Date().getTime() + 10;

					while(true){
						var next = fun.next(result);
//console.log(next.done, next.value, next.value instanceof Promise, next.value instanceof coro.promise);
						if(next.done){
							if(next.value instanceof Promise || next.value instanceof coro.promise){
								if(next.value.start) next.value.start();
								next.value.then(resolve3, reject2);
								break;
							} else {
								resolve(next.value);
								break;
							};

							//if(root) thread.running = false;
						} else {
							if(next.value instanceof Promise || next.value instanceof coro.promise){
								if(next.value.start) next.value.start();
								if(new Date().getTime() > time) {
									setTimeout(function(){
										next.value.then(resolve2,reject2);
									},0);
									break;
								} else {
									next.value.then(resolve2,reject2);
									break;
								}
							} else {
								if(new Date().getTime() > time) {
									setTimeout(callee,0,next.value);
									break;
								} else {
									result = next.value;
								}
							}
						}
					};
				})();
			}
		});

		promise.start = start;
		
		if(thread.end){
			promise.prev = thread.end;
			thread.end.next = promise;
			thread.end = promise;
		} else {
			thread.end = promise;
			start();
		};
		
		promise.then(()=>{
			if(thread.end == promise){
				if(promise.next){
					thread.end = promise.next;
					promise.next = null;
					thread.end.prev = null;
					thread.end.start();
				} else {
					coro.threads[threadIndex] = null;
				}
			} else {
				if(promise.next){
					var next = promise.next;
					promise.next.prev = null;
					promise.next = null;
					next.start();
				}
			}
		});
		
		return promise;
	};

	coro.wait = function(time){
		return new Promise(function(resolve){
			setTimeout(()=>{
				resolve();
			},time)
		});
	}

	coro.set = function(fn, thisCtx){
		coro.temp = coro.run(fn, thisCtx);
	};

	Object.defineProperty(coro, "g", {
		get(){
			var temp = coro.temp;
			coro.temp = null;
			return temp;
		}
	});

	coro.async = function(fn){
		var fun = function(){
			return coro(fn);
		};

		fun.toString = ()=>{ return fn.toString(); };
		return fun;
	};

	coro.compile = function*(input){
		var o = {
			//input 输入
			i:input,

			//output 输出
			o:[],

			//progress 编译进程
			p:0,

			//throw not end 抛出未结束异常
			t:function(){
				console.trace();
				throw "error at:" + this.p;
			},

			//write 写入
			w:function(str){ this.o.push(str); },

			//write from input
			f:function(e){
				this.o.push(this.i.substring(this.p, e));
				//this.b = this.p;
				this.p = e;
			},

			//队列
			q:[0,0,0],
			gq:function(index){
				return this.q[1-index];
			},

			//接受空格
			s:function(val){
				var r = /(?:(\s+)|.)/g

				r.lastIndex = this.p;
				var match = r.exec(this.i);
				if(match && match[1]){
					this.p = r.lastIndex;
					if(val) this.w(" ");
				}
			},

			//next char
			get n(){
				return this.i[this.p];
			},

			//in expresstion
			e:0,

			exec:function(reg){
				reg.lastIndex = this.p;
				var match = reg.exec(this.i);
				if(match) match.p = reg.lastIndex;

				return match
			}
		}

		//o.w("(()=>{ return function*(){");
		o.w("var $f=function*(){");

		var ctx = {}, fn, fn2, op;
		while(o.p < o.i.length){
			fn = [null,Block,ctx];
				
			while(fn2 = fn[1](o, fn[0], fn[2])){
				if(!fn2[2]) fn2[2] = fn[2];
				if(fn2[0] && !fn2[0][2]) fn2[0][2] = fn[2];
				fn = yield fn2;
				o.q.shift();
				o.q.push(fn[1]);

				var url = URL.createObjectURL(new Blob([o.o.join("")], {type:"text/plain"}));
				$.ajax(url,{
					async:false,
					dataType:"text",
					success:function(data){
						console.log([o.i.substring(o.p), data.substring(data.length - 50), o.e, fn[1]]);
						URL.revokeObjectURL(url);
					}
				})

			};
				
			switch(o.n){
				case ";":
					o.f(o.p+1);
					o.e=0;
					break;
				case "\n":
				case " ":
				case "\t":
					o.s();
					break;
			}

			if(o.p == op) o.t();
			op = o.p;
		}

		o.w("};var $y");
		for(var item of Object.keys(ctx)){
			o.w(",");
			o.w(item);
		}
		//o.w("})();");
		o.w(";$f");


		var url = URL.createObjectURL(new Blob([o.o.join("")], {type:"text/plain"}));
		$.ajax(url,{
			async:false,
			dataType:"text",
			success:function(data){
				console.log(data);
				URL.revokeObjectURL(url);
			}
		})


		return o.o;
	};

	coro.parse = function*(input){
		input = yield* coro.compile(input);

		return yield new Promise(function(resolve, reject) {
			var url = URL.createObjectURL(new Blob([input.join("")], {type:"text/plain"}));
			$.ajax(url,{
				async:false,
				dataType:"text",
				success:function(data){
					resolve(data);
					URL.revokeObjectURL(url);
				}
			})
		});
	};

	coro.pm = 0;
	coro.eval = function*(input){
		input = yield* coro.compile(input);

		var promise = new Promise(function(resolve, reject) {
			var pm = coro.pm++;
			
			coro["pm" + pm] = function($f){
				//URL.revokeObjectURL(url);
				delete coro["pm" + pm];
				resolve(coro.run($f));
			};
			
			input.push(";coro.pm");
			input.push(pm);
			input.push("($f)");
			var url = URL.createObjectURL(new Blob([input.join("")], {type: "text/plain"}));
			

			var script = win.$("<script type='text/javascript'>")[0];
			script.setAttribute("type", "text/javascript");
			script.setAttribute("src", url);
			win.$(win.document.head).append(script);
		});
		promise.name = "hello";
		return yield promise;
	}





	

	var Block = function(o, p){
		var r = /(?:((?:break|case|catch|continue|default|delete|do|else|finally|for|function|if|in|instanceof|new|of|return|switch|throw|try|typeof|var|void|while|with|true|false)(?![a-zA-Z0-9$_])|\"|\'|\`|\(|\,|\)|\{|\}|\[|\]|\/\/|\;)|([a-zA-Z\$\_]))/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match){
			o.f(o.i.length);
			return p;
		};
		
		if(match[1]){
			switch(match[1][0]){
				case '"':
					o.f(r.lastIndex - 1);
					return [p,DoubleQuotation];
				case "'":
					o.f(r.lastIndex - 1);
					return [p,SingleQuotation];
				case "`":
					o.f(r.lastIndex - 1);
					return [p,ReverseQuotation];
				case "(":
					o.f(r.lastIndex - 1);
					return [p,ParenthesisStart];
				case ",":
					o.f(r.lastIndex - 1);
					return p;
				case ")":
					o.f(r.lastIndex-1);
					return p;
				case "{":
					o.f(r.lastIndex-1);
					return [p,ObjStart]
				case "}":
					o.f(r.lastIndex-1);
					return p;
				case "[":
					o.f(r.lastIndex-1);
					return [p,ArrStart]
				case "]":
					o.f(r.lastIndex-1);
					return p;
				case "\/":
					o.f(r.lastIndex-2);
					return [p,Comment]
				case ";":
					o.f(r.lastIndex-1);
					o.e=0;
					return p;
				case "e":
					o.f(r.lastIndex-4);
					return [p,ElseStart];
				case "f":
					switch(match[1][1]){
						case "a":
							o.f(r.lastIndex);
							return [p,ValTarget];
						case "u":
							//throw "Please use => instead of function";
							o.f(r.lastIndex - 8); //接收到“function”之前
							return [p,Function];
						case "o":
							o.f(r.lastIndex);
							return [p,ConditionStart];
					};
					break;
				case "i":
					o.f(r.lastIndex);
					return [p,ConditionStart];
				case "n":
					o.f(r.lastIndex - 3);
					return [p,New];
				case "s":
					o.f(r.lastIndex);
					return [p,SwitchStart];
				case "t":
					o.f(r.lastIndex);
					return [p,ValTarget];
				case "v":
					o.f(r.lastIndex - 3); //接收到“var”之前
					return [p,VarStart];
				case "w":
					o.f(r.lastIndex);
					return [p,ConditionStart];
			};

			o.f(r.lastIndex);
			return [p, Block];
		} else if(match[2]){
			o.f(r.lastIndex - 1);
			return [p,ObjTargetStart];
		} else {
			o.f(r.lastIndex);
			return [p,Block];
		}
	};

	var New = function(o, p){
		o.p += 3;
		
		var match = o.exec(/([a-zA-Z0-9\$\_]+)\s*(\.?)/g);
		if(match[2]){
			o.p = match.p - 1;

			o.w("($y=");
			o.w(match[1]);

			while(match = o.exec(/\.([a-zA-Z0-9\$\_]+)\s*/g)){
				o.p = match.p;
				o.w(",");
				switch(o.n){
					case ".":
						o.w("$y=$y."); o.w(match[1]); o.w("(");
						continue;
					default:
						o.w("yield new $y."); o.w(match[1]); o.w(")");
						o.e = 1;
						return p;
					case "(":
						o.w("$y=yield new $y."); o.w(match[1]); o.w("(");
						o.p++;
						return [[p,NewEnd2], Block];
				};
			}
		} else {
			o.p = match.p
			o.w("yield new ");
			o.w(match[1]);
			o.f(o.exec(/\(/g).p);
			return [[p,NewEnd], Block];
		}
	}

	var NewEnd = function(o, p){
		switch(o.n){
			case undefined: o.t();
			case ")":
				o.f(o.p+1);
				o.e=1;
				return p;
			default:
				o.f(o.p+1);
				return [[p, NewEnd], Block];
		}
	}

	var NewEnd2 = function(o, p){
		switch(o.n){
			case undefined: o.t();
			case ")":
				o.f(o.p+1);
				o.e=1;
				return [[p, NewEnd3], ObjTarget];
			default:
				o.f(o.p+1);
				return [[p, NewEnd2], Block];
		}
	}

	function NewEnd3(o, p){
		o.w(")");
		return p;
	}

	var Comment = function(o, p){
		var r = /[\r\n]+/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(match){
			o.p = r.lastIndex;
		} else {
			o.p = o.i.length;
		}

		return p;
	}

	//for|if(){}
	var ConditionStart = function(o, p){
		var r = /\(/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		o.w("(");

		return [[p,ConditionEnd], Block];
	}

	var ConditionEnd = function(o, p){
		switch(o.n){
			case undefined: o.t();
			case ")":
				o.f(o.p+1);
				return [p, ConditionBodyStart];
			default:
				o.f(o.p+1);
				return [[p,ConditionEnd], Block];
		}
	}

	var ConditionBodyStart = function(o, p){
		var r = /\{/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		o.w("{yield;");

		return [[p,ConditionBodyEnd], Block];
	}

	var ConditionBodyEnd = function(o, p){
		o.e = 0;

		var r = /[\;\}]/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);
		switch(match[0]){
			case ";":
				return [[p,ConditionBodyEnd], Block];
			case "}":
				return p;
		}

		return p;
	}

	//switch(){}
	var SwitchStart = function(o, p){
		var r = /\(/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		o.w("(");

		return [[p,SwitchEnd], Block];
	}

	var SwitchEnd = function(o, p){
		switch(o.n){
			case undefined: o.t();
			case ")":
				o.f(o.p+1);
				return [p, SwitchBodyStart];
			default:
				o.f(o.p+1);
				return [[p,SwitchEnd], Block];
		}
	}

	var SwitchBodyStart = function(o, p){
		var r = /\{/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		o.w("{");

		return [[p,SwitchBodyEnd], Block];
	}

	var SwitchBodyEnd = function(o, p){
		o.e = 0;

		var r = /[\;\}]/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);
		switch(match[0]){
			case ";":
				return [[p,SwitchBodyEnd], Block];
			case "}":
				return p;
		}

		return p;
	}

	var ElseStart = function(o, p){
		o.w("else");
		o.p += 4;

		var r = /(?:if|\{)/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		if(match[0] == "{"){
			o.p = r.lastIndex;
			o.w("{");

			return [[p,ElseEnd], Block];
		} else {
			o.f(r.lastIndex-2);
			return p;
		}
	}

	var ElseEnd = ConditionBodyEnd;

	var VarStart = function(o, p){
		//o.w("var ");
		o.p += 3;

		return [p,VarItem];
	};

	var VarItem = function(o, p, ctx){
		var r = /([a-zA-Z0-9\_\$]+)\s*(\=|(?:of|in)(?![a-zA-Z0-9$_]))?/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		ctx[match[1]] = true;

		if(match[2]){
			o.w(match[1]);
			switch(match[2][0]){
				case "=": o.w("="); break;
				case "o": o.w(" of"); break;
				case "i": o.w(" in"); break;
			}
			return [[p, VarEnd], Block];
		} else {
			var r = /(?:(\,)|([^\s]?))/g
			r.lastIndex = o.p;
			var match = r.exec(o.i);
			if(!match) o.t();

			if(match[1] == ","){
				o.p = r.lastIndex;
				return [p, VarItem]
			} else {
				o.f(r.lastIndex - match[2].length);
				return [p, Block];
			}
		}
	};

	var VarEnd = function(o, p){
		var r = /(?:(\,)|([^\s]))/g
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) return p;
		
		if(match[1]){
			switch(match[0]){
				case ",":
					o.p = r.lastIndex;
					o.w(";");
					return [p, VarItem];
				default:
					throw o.t();
			}
		} else if(match[2]){
			o.f(r.lastIndex - 1);
			o.w(" ");
			return [p, Block];
		}
	};

	var ParenthesisStart = function(o, p){
		o.e=0;
		o.p++;

		var r = /(?:([a-zA-Z0-9\_\$\,\=\s]*\)\s*\=\>)|(.))/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		if(match[1]){
			o.w("(");
			return [[p,ArrowFuncBodyStart,{}],Arguments]
		} else {
			o.w("($y=yield(");
			return [[p,ParenthesisEnd],Block];
		}
	};

	var ParenthesisEnd = function(o, p){
		var r = /(?:\)|\,)/g;

		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();
		
		switch(match[0]){
			case ")":
				o.p = r.lastIndex;
				o.w("))");
				return [p,ObjTarget];
			case ",":
				o.e = 0;
				o.f(r.lastIndex);
				return [[p,ParenthesisEnd],Block];
		}
	};

	var DoubleQuotation = function(o, p){
		o.f(o.p + 1); //接收符号“"”

		var r = /(?:\\.|\")/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);
		switch(match[0][0]){
			case "\\": return [p, DoubleQuotation];
			case '"': return p;
		}
	};

	function SingleQuotation(){
		o.f(o.p + 1); //接收符号“'”

		var r = /(?:\\.|\')/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);
		switch(match[0][0]){
			case "\\": return [p, SingleQuotation];
			case "'": return p;
		}
	};

	function ReverseQuotation(o, p){
		o.f(o.p + 1); //接收符号“`”

		return [p, ReverseQuotationStr];
	}

	function ReverseQuotationStr(o, p){
		var match = o.exec(/(?:\`|\\.|\$\{)/g);
		o.f(match.p);
		switch(match[0][0]){
			case "`":
				return [p, ValTarget];
			case "\\":
				return [p,ReverseQuotationStr];
			case "$":
				return [[p, ReverseQuotationExpr], Block];
		}
	}

	function ReverseQuotationExpr(o, p){
		switch(o.n){
			case "}":
				o.f(o.p+1);
				return p;
			default:
				o.f(o.p+1);
				return [[p, ReverseQuotationExpr], Block];
		}
	}

	var Function = function(o, p){
		o.f(o.p + 8); //接收“function”

		var r2 = /\(/g;

		//接收符号“(”
		r2.lastIndex = o.p;
		if(!r2.exec(o.i)){ o.t(); }
		o.f(r2.lastIndex);

		return [[p,FunctionBodyStart,{}],Arguments]
	};

	var Arguments = function(o, p){
		var r = /(?:function|\"|\'|\`|\))/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		switch(match[0][0]){
			case '"':
				o.f(r.lastIndex - 1);
				return [[p,Function],DoubleQuotation];
			case "'":
				o.f(r.lastIndex - 1);
				return [[p,Function],SingleQuotation];
			case "`":
				o.f(r.lastIndex - 1);
				return [[p,Function],ReverseQuotation];
			case "f":
				o.f(r.lastIndex - 8); //接收到“function”之前
				return [[p,Function],Function];
			case ")":
				o.f(r.lastIndex);
				return p;
		}
	}

	var FunctionBodyStart = function(o, p){
		var r = /\{/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		o.w("{");
		o.w("return coro.run(function*(){");
		return [[p,FunctionBodyEnd], Block];
	};

	var FunctionBodyEnd = function(o, p, ctx){
		switch(o.n){
			case undefined:o.t();
			case "}":
				o.p++;
				o.w("},this);var $y");
				for(var item of Object.keys(ctx)){
					o.w(",");
					o.w(item);
				}
				o.w("}");
				return p;
			default:
				o.f(o.p+1);
				return [[p,FunctionBodyEnd], Block];
		}
	}

	var ArrowFuncBodyStart = function(o, p){
		var r = /\{/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		o.w("=>{");
		o.w("return coro.run(function*(){");
		//return [[p,FunctionBody], Block];
		return [[p,FunctionBodyEnd], Block];
	}

	var ObjFuncInvoke = function(o, p){
		o.w("$y=yield $y");
		o.f(o.p + 1); //接收括号“(”

		return [[p,ObjFuncInvokeEnd], Block];
	};

	var ObjFuncInvokeEnd = function(o, p){
		var r = /[\,\)]/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);

		switch(match[0]){
			case ",":
				return [[p,ObjFuncInvokeEnd], Block];
			case ")":
				return [p, ObjTarget];
		}
	};

	var ObjStart = function(o, p){
		o.f(o.p+1);

		return [p, ObjMember];
	}

	var ObjMember = function(o, p){
		var r = /(?:(?:(?:get|set)\s+)?[a-zA-Z0-9\$\_]+|([\"\'\}]))/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);
		if(match[1]){
			switch(match[1]){
				case '"':
					o.f(r.lastIndex);
					return [p,DoubleQuotation];
				case "'":
					o.f(r.lastIndex);
					return [p,SingleQuotation];
				case "}":
					o.e=1;
					return p;
				default: o.t();
			}
		} else {
			o.e=0;
			return [[p,ObjMember], Block];
		}
	}

	var ObjEnd = function(o, p){
		var chr = o.i[o.p];
		o.f(o.p+1);

		switch(chr){
			case "}":
				return p;
			case ",":
				return [p, ObjMember];
			default:
				return [[p,ObjEnd], Block];
		}

		if(chr == "}"){
			return p;
		} else {
			return [[p,ObjEnd], Block];
		}
	}

	var ObjTargetStart = function(o, p){
		if(o.e) o.w(";");

		var r = /([a-zA-Z0-9\$\_]+)\s*(\.|\(|\[|\=|\+\+|\-\-)?/g;

		r.lastIndex = o.p;
		var match = r.exec(o.i);

		if(match[2]){
			o.e = 0;
			switch(match[2][0]){
				case "=":
				case "+":
				case "-":
					o.w(match[1]);
					o.p=r.lastIndex;
					o.w(match[2]);
					return [p,Block]; //这里可能错误
					break;
			}
		};

		o.w("(");
		if(match[2]){
			o.w("$y=");
		};
		o.w("yield ");
		o.w(match[1]);
		
		if(match[2]){
			o.p = r.lastIndex - 1;
			o.w(",");
			switch(match[2]){
				case '.':
					return [[p,ObjTargetEnd2],ObjNameMember];
				case "[":
					return [[p,ObjTargetEnd2],ObjArrMember]; 
				case "(":
					return [[p,ObjTargetEnd2],ObjFuncInvoke];
			};
		} else {
			o.w(")");
			o.p = r.lastIndex;
			return p;
		};
	};

	var ObjTargetEnd2 = function(o, p){
		o.w(")");
		o.e=1;

		return p;
	}

	var ObjTarget = function(o, p){
		o.e=0;
		var r = /(?:(\.|\(|\[|\`|\/\/)|[^\s])/g;

		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match){
			return p;
		};
		
		if(match[1]){
			switch(match[1][0]){
				case '.':
					o.p = r.lastIndex - 1;
					o.w(",");
					return [p,ObjNameMember];
				case "[":
					o.f(r.lastIndex - 1);
					o.w(",");
					return [p,ObjArrMember]; 
				case "(":
					o.f(r.lastIndex - 1);
					o.w(",");
					return [p,ObjFuncInvoke];
				case "`":
					o.f(r.lastIndex - 1);
					return [p,ObjRevMember];
				case "\/":
					return [[p,ObjTarget],Comment];
			}
		} else {
			o.f(r.lastIndex - 1); //这里可能匹配到只有1个字符
			return p;
		}
	};

	function ObjRevMember(o, p){
		o.w(",$y=$y");
		o.f(o.p+1);
		return [p,ObjRevMemberStr];
	};

	function ObjRevMemberStr(o, p){
		var match = o.exec(/(?:\`|\\.|\$\{)/g);
		o.f(match.p);
		switch(match[0][0]){
			case "`":
				return [p, ObjTarget];
			case "\\":
				return [p,ObjRevMemberStr];
			case "$":
				return [[p, ObjRevMemberExpr], Block];
		}
	}

	function ObjRevMemberExpr(o, p){
		switch(o.n){
			case "}":
				o.f(o.p+1);
				return p;
			default:
				o.f(o.p+1);
				return [[p, ReverseQuotationExpr], Block];
		}
	}

	var ObjNameMember = function(o, p){
		var r = /(?:([a-zA-Z0-9]+)\s*(\=|\()?|([^\s]))/g;

		r.lastIndex = o.p + 1;
		var match = r.exec(o.i);

		if(match && match[1]){
			if(match[2]){
				switch(match[2]){
					case "=":
						o.w("$y=$y.");
						o.w(match[1]);
						o.p = r.lastIndex;
						o.w("=");
						return [[p, ObjNameEqual], Block];
					case "(":
						o.w("$y=yield(yield $y.");
						o.w(match[1]);
						o.w(")");
						o.p = r.lastIndex - 1;
						return [[p, ObjTarget], FunctionInvoke]
				}
			} else {
				o.w("$y=yield $y.");
				o.w(match[1]);
				o.p = r.lastIndex;
				return [p, ObjTarget];
			}
		} else {
			o.t();
		};
	};

	var ObjNameEqual = function(o, p){
		o.w(",yield coro.g,$y");
		return p;
	}

	var FunctionInvoke = function(o, p){
		o.w(".call");
		o.f(o.p + 1); //接收括号“(”
		
		o.s();
		o.w("$y");
		
		if(o.n != ")") o.w(",");

		return [[p,FunctionInvokeEnd], Block];
	};

	var FunctionInvokeEnd = function(o, p){
		var r = /[\,\)]/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);

		switch(match[0]){
			case ",":
				return [[p,FunctionInvokeEnd], Block];
			case ")":
				return [p, ObjTarget];
		}
	};

	var ObjArrMember = function(o, p){
		o.w("$y=yield $y");
		o.f(o.p + 1);

		return [[p, ObjArrEnd], Block];
	};

	var ObjArrEnd = function(o, p){
		var r = /\]\s*(\=)?/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.p = r.lastIndex;
		if(match[1]){
			o.w("]=");
			return [p, Block];
		} else {
			o.w("]");
			return [p, ObjTarget];
		}
	}

	var ArrStart = function(o, p){
		o.p++;
		o.w("[");
		
		return [[p, ArrEnd], Block];
	}

	var ArrEnd = function(o, p){
		var r = /[\,\]]/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);
		switch(match[0]){
			case ",":
				return [[p, ArrEnd], Block];
				break;
			case "]":
				return [p, ValTarget];
		}
	}

	var ValTarget = function(o, p){
		var r = /(?:\.|\(|\[|[^\s])/g;

		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match){
			return p;
		};
		
		switch(match[0][0]){
			case '.':
				o.p = r.lastIndex - 1;
				return [p,ValNameMember];
			case "[":
				o.f(r.lastIndex - 1);
				return [p,ValArrMember]; 
			case "(":
				o.f(r.lastIndex - 1);
				return [p,ValFuncInvoke];
			default:
				o.f(r.lastIndex - 1); //这里可能匹配到只有1个字符
				return p;
		}
	}

	var ValNameMember = function(o, p){
		var r = /(?:([a-zA-Z0-9]+)\s*(\=)?|([^\s]))/g;

		r.lastIndex = o.p + 1;
		var match = r.exec(o.i);

		if(match && match[1]){
			if(match[2]){
				o.w(".");
				o.w(match[1]);
				o.p = r.lastIndex;
				o.w("=");
				return [p, Block];
			} else {
				o.w(".");
				o.w(match[1]);
				o.p = r.lastIndex;
				return [p, ValTarget];
			}
		} else {
			o.t();
		};
	};

	var ValFuncInvoke = function(o, p){
		o.f(o.p + 1); //接收括号“(”

		return [[p,ValFuncInvokeEnd], Block];
	};

	var ValFuncInvokeEnd = function(o, p){
		var r = /[\,\)]/g;
		r.lastIndex = o.p;
		var match = r.exec(o.i);
		if(!match) o.t();

		o.f(r.lastIndex);

		switch(match[0]){
			case ",":
				return [[p,ValFuncInvokeEnd], Block];
			case ")":
				return [p, ValTarget];
		}
	};

	var ValArrMember = function(o, p){
		o.f(o.p + 1);

		return [[p, ArrEnd], Block];
	}

	//createCurrentScriptFragment
	/*
	win.CCSF = function(){
		var script = win.document.getElementsByTagName("script");
		script = script[script.length - 1];
		//var fragment = win.document.createDocumentFragment();
		//script.parentNode.replaceChild(fragment, script);

		var last;
		return {
			appendChild:function(child){
				if(child instanceof win.Text){
					var span = win.document.createElement("span");
					span.appendChild(child);
					child = span;
				};

				if(last){
					last = last.parentNode.insertBefore(child, last.nextSibling)
				} else {
					script.parentNode.replaceChild(child, script);
					last = child;
					script = null;
				}
			}
		};
	};
	*/



})(window);
